package cn.edu.sjtu.se.dslab.controller;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import cn.edu.sjtu.se.dslab.action.bean.PageBean;
import cn.edu.sjtu.se.dslab.component.data.DataComponent;
import cn.edu.sjtu.se.dslab.component.data.DomainEntity;
import cn.edu.sjtu.se.dslab.component.data.util.DataComponentUtil;
import cn.edu.sjtu.se.dslab.service.IAvionicsEquipmentService;
import cn.edu.sjtu.se.dslab.service.IDataComponentService;
import cn.edu.sjtu.se.dslab.service.IDataTypeService;
import cn.edu.sjtu.se.dslab.service.IDomainEntityService;
import cn.edu.sjtu.se.dslab.util.Const;
import cn.edu.sjtu.se.dslab.util.PackUtil;

@Controller
@RequestMapping(value = "/component")
public class DataComponentController {

	@Resource(name = "dataComponentService")
	IDataComponentService dataComponentService;
	
	@Resource(name = "dataComponentUtil")
	DataComponentUtil dataComponentUtil;
	
	@Resource(name="avionicsEquipmentService")
	IAvionicsEquipmentService avionicsEquipmentService;
	
	@Resource(name = "dataTypeService")
	IDataTypeService dataTypeService;
	
	@Resource(name = "domainEntityService")
	IDomainEntityService domainEntityService;

	@RequestMapping(value = "/data_component", method = RequestMethod.GET)
	public ModelAndView getDataComponentList(
			@RequestParam(value = "pageNum", defaultValue = "1") int pageNUm) {
		ModelAndView model = new ModelAndView();
		model.setViewName("data_component");
		try {
			PageBean<DataComponent> bean = dataComponentService
					.getPageBean(pageNUm);
			model.addObject("bean", bean);
			return model;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return model;
	}
	
	@RequestMapping(value = "/data_component/search", method = RequestMethod.POST)
	public ModelAndView searchDataComponent(
			String searchText,String ctype) {
		ModelAndView model = new ModelAndView();
		model.setViewName("domain_entity_nopage");
		try {
			List mylist = new ArrayList();
			if(ctype == null || ctype.equals("")){
				List<DomainEntity> temp1 = domainEntityService.getDomainEntityByText(searchText);
				List temp2 = dataTypeService.getDataTypeByText(searchText);
				List temp3 = avionicsEquipmentService.getAvionicsEquipmentByText(searchText);
				mylist.addAll(temp1);
				mylist.addAll(temp2);
				mylist.addAll(temp3);
			}else if (ctype.equals("data")) {
				mylist = domainEntityService.getDomainEntityByText(searchText);
			}else if (ctype.equals("type")) {
				mylist = dataTypeService.getDataTypeByText(searchText);
			}else if (ctype.equals("equipment")) {
				mylist = avionicsEquipmentService.getAvionicsEquipmentByText(searchText);
			}
			model.addObject("mylist", mylist);
			return model;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return model;
	}

	@RequestMapping(value = "/data_component/{uri}", method = RequestMethod.GET)
	public ModelAndView getDataComponentByUri(
			@PathVariable(value = "uri") String uri) {
		ModelAndView model = new ModelAndView();
		try {
			DataComponent component = dataComponentService
					.getDataComponentByUri(Const.URI_DATA_COMPONENT+":"+uri);
			if (component != null) {
				model.setViewName("data_cpnt_detail");
				model.addObject("item", component);
			}
			return model;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return model;
	}
	@RequestMapping(value = "/data_component/{uri}/delete", method = RequestMethod.GET)
	public String deleteDataComponentByUri(
			@PathVariable(value = "uri") String uri) {
		try {
			DataComponent component = dataComponentService
					.getDataComponentByUri(Const.URI_DATA_COMPONENT+":"+uri);
			component.setDeleted(true);
			dataComponentService.updateDataComponent(component);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return "redirect:/component/data_component";
	}
	
	/**
	 * 下载该uri对应的文件所有文件，zip打包，以该component的名称命名 
	 * @param uri
	 * @return
	 */
	@RequestMapping(value = "/data_component/{uri}/download",method = RequestMethod.GET)
	public void downloadDataComponentByUri(
			@PathVariable(value = "uri") String uri, HttpServletResponse response) throws FileNotFoundException,IOException{
			//将所有文件打包下载，包括继承项，组合项和依赖项
			DataComponent component = dataComponentService
					.getDataComponentByUri(Const.URI_DATA_COMPONENT + ":"+uri);
			if (component != null) {
				Map<Long , String> fileMap = dataComponentUtil.getDependence(component.getEntity());
				//包含所有的依赖文件的绝对路径
				List<String> filePaths = new ArrayList<String>(fileMap.values());
				//打包文件名称
				String zipName = component.getName()+".zip";
				//打包文件保存路径-uri对应的文件夹下 
				String zipDir = Const.COMPONENT_GENERATE_PATH+component.getUri().split(":")[component.getUri().split(":").length -1];
				//获取绝对路径
				String realPath = Const.ABSOLUTE_GENERATE_PATH+zipDir;
				realPath = realPath.replace("\\", "/");
				for (int i = 0; i < filePaths.size(); i++) {
					filePaths.set(i, filePaths.get(i).replace("\\", "/"));
				}
//				System.out.println(filePaths.iterator().next());
//				System.out.println(realPath);
//				System.out.println(zipName);
				boolean result =PackUtil.zipList(filePaths,realPath , zipName);
				//server运行正确，成功打包
				if (result) {
					//System.out.print("result:"+result);
					File file = new File(realPath+"/"+zipName);
					InputStream is = new FileInputStream(file);
					// set content attributes for the response
					response.setContentType("application/octet-stream");
					response.setContentLength((int) file.length());
					// set headers for the response
			        String headerKey = "Content-Disposition";
			        String headerValue = String.format("attachment; filename=\"%s\"",
			        		zipName);
			        response.setHeader(headerKey, headerValue);
					IOUtils.copy(is, response.getOutputStream());
					response.flushBuffer();
				}else {
					String tips = "服务器错误，请稍后再试！";
					InputStream isInputStream = new ByteArrayInputStream(tips.getBytes("utf-8"));
					response.setContentType("text/plain");
					response.setContentLength(tips.getBytes("utf-8").length);
					IOUtils.copy(isInputStream, response.getOutputStream());
					response.flushBuffer();
				}
				
			}else {
				return;
			}
	}
	
	@ExceptionHandler({IOException.class,FileNotFoundException.class})
	public ResponseEntity<String> handleIOException(IOException ex) {
	    // prepare responseEntity
		HttpHeaders headers = new HttpHeaders();  
        headers.setContentType(MediaType.TEXT_PLAIN);
		ResponseEntity<String> responseEntity =new ResponseEntity<String>("The server has some errors,please try later!", headers,HttpStatus.OK);
	    return responseEntity;
	}
}
